import netCDF4 as nc
import numpy as np
import matplotlib
# 设置matplotlib使用非交互式后端，解决多线程环境中的GUI问题
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cartopy.io.img_tiles as cimgt
from matplotlib.colors import Normalize
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any, List
import os
import uuid
from pathlib import Path
import time
import glob
from PIL import Image
import re
import tempfile
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False

# 配置路径
DATA_DIR = "data"
OUTPUT_DIR = "img"
TIANDITU_KEY = "ab9739c6cd06499bc9d8959470fd4da3"

# 创建输出目录
os.makedirs(OUTPUT_DIR, exist_ok=True)


# 天地图瓦片类
class TianDiTu(cimgt.GoogleWTS):
    def __init__(self, key, layer='ter', tilematrixset='c'):
        super().__init__()
        self.key = key
        self.layer = layer
        self.tilematrixset = tilematrixset
        self._url = f"http://t0.tianditu.gov.cn/{layer}_{tilematrixset}/wmts?" \
                    f"SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0" \
                    f"&LAYER={layer}&STYLE=default&TILEMATRIXSET={tilematrixset}" \
                    f"&TILEMATRIX={{z}}&TILEROW={{y}}&TILECOL={{x}}&FORMAT=tiles&tk={key}"
        self.subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']
        # self.tile_size = 256

    def _image_url(self, tile):
        x, y, z = tile
        subdomain = self.subdomains[(x + y) % len(self.subdomains)]
        return self._url.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(z)).replace("{s}", subdomain)


class PlottingParameters(BaseModel):
    """绘图参数模型"""
    nc_filename: str = Field(description="NC文件名（不包含路径，文件应在data文件夹中）")
    variable: str = Field(description="要绘制的变量名")
    level: Optional[int] = Field(default=0, description="数据层级（对于3D数据）")
    
    # 可选的流速数据
    uv_nc_filename: Optional[str] = Field(default=None, description="流速数据NC文件名")
    u_var: Optional[str] = Field(default=None, description="u分量变量名")
    v_var: Optional[str] = Field(default=None, description="v分量变量名")
    
    # 图例和颜色条配置
    vmin: Optional[float] = Field(default=None, description="图例最小值（用于单张图片）")
    vmax: Optional[float] = Field(default=None, description="图例最大值（用于单张图片）")
    num_levels: int = Field(default=20, description="等值线级数")
    integer_levels: bool = Field(default=True, description="是否使用整数等值线级别")
    colorbar_extend: str = Field(default='neither', description="图例箭头 'neither', 'both', 'min', 'max'")

    # 输出配置
    output_filename: Optional[str] = Field(default=None, description="输出图片文件名")
    figsize: tuple = Field(default=(12, 10), description="图像尺寸（宽度,高度）英寸")
    dpi: int = Field(default=300, description="输出图像分辨率")
    title: Optional[str] = Field(default=None, description="地图标题")
    
    # 地图元素控制
    add_north_arrow: bool = Field(default=True, description="是否添加指北针")
    add_scale_bar: bool = Field(default=True, description="是否添加比例尺")
    scale_bar_length: float = Field(default=200, description="比例尺长度（单位：km）")
    skip_arrows: int = Field(default=1, description="流速箭头绘制间隔")
    
    # GIF动画配置
    create_gif: bool = Field(default=False, description="是否生成GIF动画")
    gif_file_pattern: Optional[str] = Field(default=None, description="GIF文件匹配模式，如'chinasea_*_temp.nc'")
    gif_duration: float = Field(default=0.8, description="GIF每帧持续时间（秒）")
    gif_loop: int = Field(default=0, description="GIF循环次数，0表示无限循环")
    gif_vmin: Optional[float] = Field(default=None, description="GIF图例最小值（固定图例范围）")
    gif_vmax: Optional[float] = Field(default=None, description="GIF图例最大值（固定图例范围）")
    gif_levels: Optional[int] = Field(default=20, description="GIF等值线级数")
    gif_integer_levels: bool = Field(default=True, description="是否使用整数等值线级别")


def create_hydrology_map(params: PlottingParameters) -> Dict[str, Any]:
    # 如果需要创建GIF，调用GIF生成函数
    if params.create_gif:
        return create_hydrology_gif(params)
    
    try:
        # 清理现有的图形，防止内存泄漏和线程冲突
        plt.close('all')
        # 构建文件路径
        nc_file_path = os.path.join(DATA_DIR, params.nc_filename)
        
        # 检查文件是否存在
        if not os.path.exists(nc_file_path):
            return {
                "status": "error",
                "message": f"NC文件不存在: {nc_file_path}",
                "output_path": None
            }
        
        # 读取温度数据
        temp_data = nc.Dataset(nc_file_path)
        lon = temp_data.variables['lon'][:]
        lat = temp_data.variables['lat'][:]
        temp = temp_data.variables[params.variable][params.level, :, :]
        
        # 处理掩码数组
        if hasattr(temp, 'data'):
            temp = temp.data
        
        # 将异常值设为NaN，这样matplotlib会自动处理它们
        temp = np.where(
            (temp >= 9000) | (temp <= -9000) | ~np.isfinite(temp),
            np.nan,
            temp
        )
        
        # 确定颜色范围和级别
        if params.vmin is not None:
            vmin = params.vmin
        else:
            # 使用有效数据的范围
            valid_data = temp[~np.isnan(temp)]
            if len(valid_data) > 0:
                vmin = float(np.percentile(valid_data, 1))
            else:
                vmin = 0
                
        if params.vmax is not None:
            vmax = params.vmax
        else:
            # 使用有效数据的范围
            valid_data = temp[~np.isnan(temp)]
            if len(valid_data) > 0:
                vmax = float(np.percentile(valid_data, 99))
            else:
                vmax = 30
        
        if params.integer_levels:
            vmin = np.floor(vmin)
            vmax = np.ceil(vmax)
        
        levels = np.linspace(vmin, vmax, params.num_levels)
        if params.integer_levels:
            levels = np.unique(np.round(levels).astype(int))

        # 创建地图对象
        tiler = TianDiTu(key=TIANDITU_KEY, layer='ter', tilematrixset='c')
        crs = tiler.crs
        
        fig = plt.figure(figsize=params.figsize)
        ax = plt.axes(projection=crs)
        
        # 添加天地图底图
        # ax.add_image(tiler, 5) # 5是缩放级别
        ax.set_extent([lon.min(), lon.max(), lat.min(), lat.max()], crs=ccrs.PlateCarree())
        
        # 绘制温度等值图
        cf = ax.contourf(lon, lat, temp, levels=levels, cmap='jet', vmin=vmin, vmax=vmax,
                         extend=params.colorbar_extend, transform=ccrs.PlateCarree())
        
        # 添加颜色条
        cbar = plt.colorbar(cf, ax=ax, orientation='vertical', pad=0.02, aspect=30, shrink=0.6)
        cbar.ax.set_yticklabels([f'{int(t)}' for t in levels])

        # 如果有流速数据则绘制
        if params.uv_nc_filename and params.u_var and params.v_var:
            uv_file_path = os.path.join(DATA_DIR, params.uv_nc_filename)
            if os.path.exists(uv_file_path):
                uv_data = nc.Dataset(uv_file_path)
                u = uv_data.variables[params.u_var][params.level, :, :]
                v = uv_data.variables[params.v_var][params.level, :, :]
                
                # 处理流速数据中的异常值
                if hasattr(u, 'data'):
                    u = u.data
                if hasattr(v, 'data'):
                    v = v.data
                
                # 将异常值设为NaN
                u = np.where(
                    (u >= 9000) | (u <= -9000) | ~np.isfinite(u),
                    np.nan,
                    u
                )
                v = np.where(
                    (v >= 9000) | (v <= -9000) | ~np.isfinite(v),
                    np.nan,
                    v
                )
                
                # 绘制流速箭头
                ax.quiver(lon[::params.skip_arrows], lat[::params.skip_arrows],
                          u[::params.skip_arrows, ::params.skip_arrows], 
                          v[::params.skip_arrows, ::params.skip_arrows],
                          color='black', scale=20, width=0.002, transform=ccrs.PlateCarree())
                
                # 添加流速比例尺
                scale_lon = np.array([lon.min() + 0.1 * (lon.max() - lon.min())])
                scale_lat = np.array([lat.max() - 0.1 * (lat.max() - lat.min())])
                scale_u = np.array([0.5])
                scale_v = np.array([0])
                ax.quiver(scale_lon, scale_lat, scale_u, scale_v, color='black',
                          scale=20, width=0.002, transform=ccrs.PlateCarree())
                ax.text(scale_lon[0], scale_lat[0] + 0.5, '0.5 m/s', fontsize=10,
                        transform=ccrs.PlateCarree())
                
                uv_data.close()
        # 添加比例尺
        if params.add_scale_bar:
            add_custom_scalebar(ax, length_km=params.scale_bar_length)
        
        # 添加指北针
        if params.add_north_arrow:
            add_fancy_north_arrow(ax)
        
        # 添加地图要素
        ax.add_feature(cfeature.LAND, facecolor='lightgray')
        ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
        
        # 添加经纬网
        gl = ax.gridlines(draw_labels=True, xlocs=None, ylocs=None)
        gl.top_labels = False
        gl.right_labels = False
        gl.xformatter = LONGITUDE_FORMATTER
        gl.yformatter = LATITUDE_FORMATTER
        
        # 设置标题
        if params.title:
            ax.set_title(params.title, fontsize=14)
        # 处理输出路径
        if params.output_filename is None:
            output_filename = f"hydrology_map_{uuid.uuid4().hex[:8]}.png"
        else:
            output_filename = params.output_filename
            
        output_path = os.path.join(OUTPUT_DIR, output_filename)
        
        # 确保输出目录存在
        Path(output_path).parent.mkdir(parents=True, exist_ok=True)
        plt.savefig(output_path, bbox_inches='tight', dpi=params.dpi)
        # 关闭数据文件
        temp_data.close()
        
        # 记录成功返回数据
        result = {
            "status": "success",
            "output_path": os.path.abspath(output_path),
            "relative_path": output_path,
            "metadata": {
                "nc_file": params.nc_filename,
                "variable": params.variable,
                "level": params.level,
                "uv_file": params.uv_nc_filename,
                "u_var": params.u_var,
                "v_var": params.v_var,
                "extent": [float(lon.min()), float(lon.max()), float(lat.min()), float(lat.max())],
                "size_inches": params.figsize,
                "dpi": params.dpi,
                "title": params.title,
                "north_arrow": params.add_north_arrow,
                "scale_bar": params.add_scale_bar,
                "scale_bar_length": params.scale_bar_length if params.add_scale_bar else None,
                "basemap": "TianDiTu"
            }
        }
        
        # 确保图形被正确关闭
        plt.close(fig)
        plt.close('all')
        
        return result
        
    except Exception as e:
        # 错误处理时确保所有资源被正确清理
        try:
            plt.close('all')
            # 尝试关闭可能打开的文件
            if 'temp_data' in locals():
                temp_data.close()
            if 'uv_data' in locals():
                uv_data.close()
        except:
            pass
        
        return {
            "status": "error",
            "message": str(e),
            "output_path": None
        }


def create_hydrology_gif(params: PlottingParameters) -> Dict[str, Any]:
    """
    创建水文地图GIF动画的函数
    
    Args:
        params: 绘图参数
        
    Returns:
        包含状态、输出路径和元数据的字典
    """
    try:
        # 清理现有的图形，防止内存泄漏和线程冲突
        plt.close('all')
        
        # 检查必需的参数
        if not params.gif_file_pattern:
            return {
                "status": "error",
                "message": "生成GIF需要提供gif_file_pattern参数",
                "output_path": None
            }
        
        # 查找匹配的文件
        file_pattern = os.path.join(DATA_DIR, params.gif_file_pattern)
        nc_files = glob.glob(file_pattern)
        
        if not nc_files:
            return {
                "status": "error",
                "message": f"没有找到匹配的文件: {file_pattern}",
                "output_path": None
            }
        
        # 排序文件以确保时间顺序
        nc_files.sort()
        print(f"找到 {len(nc_files)} 个文件用于生成GIF")
        
        # 如果没有指定图例范围，先扫描所有文件确定数值范围
        if params.gif_vmin is None or params.gif_vmax is None:
            print("正在扫描文件以确定数值范围...")
            all_values = []
            for file_path in nc_files:
                try:
                    with nc.Dataset(file_path) as dataset:
                        data = dataset.variables[params.variable][params.level, :, :]
                        
                        # 处理掩码数组
                        if hasattr(data, 'data'):
                            data = data.data
                        
                        # 去除NaN、无限值和异常填充值（如9999、-9999等）
                        valid_mask = (
                            ~np.isnan(data) & 
                            np.isfinite(data) & 
                            (data < 9000) &  # 去除大于9000的异常值
                            (data > -9000)   # 去除小于-9000的异常值
                        )
                        
                        valid_data = data[valid_mask]
                        
                        if len(valid_data) > 0:
                            all_values.extend(valid_data.flatten())
                            print(f"文件 {os.path.basename(file_path)}: 有效数据 {len(valid_data)}/{data.size} 个")
                        else:
                            print(f"文件 {os.path.basename(file_path)}: 没有有效数据")
                            
                except Exception as e:
                    print(f"警告：无法读取文件 {file_path}: {e}")
                    continue
            
            if not all_values:
                return {
                    "status": "error",
                    "message": "无法从任何文件中读取有效数据",
                    "output_path": None
                }
            
            all_values = np.array(all_values)
            
            # 使用更合理的方法确定范围
            if params.gif_vmin is None:
                # 使用1%分位数避免极端值
                vmin = float(np.percentile(all_values, 1))
            else:
                vmin = params.gif_vmin
                
            if params.gif_vmax is None:
                # 使用99%分位数避免极端值
                vmax = float(np.percentile(all_values, 99))
            else:
                vmax = params.gif_vmax
        else:
            vmin = params.gif_vmin
            vmax = params.gif_vmax
        
        print(f"使用数值范围: {vmin:.2f} - {vmax:.2f}")
        
        # 创建等值线级别
        num_levels = params.gif_levels or 20  # 如果为None，使用默认值20
        if params.gif_integer_levels:
            # 使用整数级别
            levels = np.linspace(int(np.floor(vmin)), int(np.ceil(vmax)), num_levels)
            levels = np.round(levels).astype(int)
        else:
            levels = np.linspace(vmin, vmax, num_levels)
        
        # 创建临时目录保存各帧图片
        temp_dir = tempfile.mkdtemp()
        frame_paths = []
        
        try:
            # 生成每一帧
            for i, nc_file in enumerate(nc_files):
                print(f"正在生成第 {i+1}/{len(nc_files)} 帧: {os.path.basename(nc_file)}")
                
                # 读取数据
                with nc.Dataset(nc_file) as dataset:
                    if i == 0:
                        # 第一个文件，获取经纬度信息
                        lon = dataset.variables['lon'][:]
                        lat = dataset.variables['lat'][:]
                    
                    data = dataset.variables[params.variable][params.level, :, :]
                    
                    # 处理掩码数组
                    if hasattr(data, 'data'):
                        data = data.data
                    
                    # 将异常值设为NaN，这样matplotlib会自动处理它们
                    data = np.where(
                        (data >= 9000) | (data <= -9000) | ~np.isfinite(data),
                        np.nan,
                        data
                    )
                
                # 创建地图
                tiler = TianDiTu(key=TIANDITU_KEY, layer='ter', tilematrixset='c')
                crs = tiler.crs
                
                fig = plt.figure(figsize=params.figsize)
                ax = plt.axes(projection=crs)
                
                # 设置地图范围
                ax.set_extent([lon.min(), lon.max(), lat.min(), lat.max()], crs=ccrs.PlateCarree())
                
                # 绘制等值图，使用固定的级别和范围
                cf = ax.contourf(lon, lat, data, levels=levels, cmap='jet', 
                                vmin=vmin, vmax=vmax, extend=params.colorbar_extend,
                                transform=ccrs.PlateCarree())
                
                # 添加颜色条（整数标签）
                cbar = plt.colorbar(cf, ax=ax, orientation='vertical', pad=0.02, aspect=30, shrink=0.6)
                cbar.ax.set_yticklabels([f'{int(t)}' for t in levels])

                # 添加流速数据（如果有）
                if params.uv_nc_filename and params.u_var and params.v_var:
                    # 构建对应的流速文件名
                    base_name = os.path.basename(nc_file)
                    uv_pattern = params.uv_nc_filename.replace('*', base_name.split('_')[1])
                    uv_file_path = os.path.join(DATA_DIR, uv_pattern)
                    
                    if os.path.exists(uv_file_path):
                        with nc.Dataset(uv_file_path) as uv_data:
                            u = uv_data.variables[params.u_var][params.level, :, :]
                            v = uv_data.variables[params.v_var][params.level, :, :]
                            
                            # 处理流速数据中的异常值
                            if hasattr(u, 'data'):
                                u = u.data
                            if hasattr(v, 'data'):
                                v = v.data
                            
                            # 将异常值设为NaN
                            u = np.where(
                                (u >= 9000) | (u <= -9000) | ~np.isfinite(u),
                                np.nan,
                                u
                            )
                            v = np.where(
                                (v >= 9000) | (v <= -9000) | ~np.isfinite(v),
                                np.nan,
                                v
                            )
                            
                            # 绘制流速箭头
                            ax.quiver(lon[::params.skip_arrows], lat[::params.skip_arrows],
                                      u[::params.skip_arrows, ::params.skip_arrows], 
                                      v[::params.skip_arrows, ::params.skip_arrows],
                                      color='black', scale=20, width=0.002, 
                                      transform=ccrs.PlateCarree())
                
                # 添加比例尺
                if params.add_scale_bar:
                    add_custom_scalebar(ax, length_km=params.scale_bar_length)
                
                # 添加指北针
                if params.add_north_arrow:
                    add_fancy_north_arrow(ax)
                
                # 添加地图要素
                ax.add_feature(cfeature.LAND, facecolor='lightgray')
                ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
                
                # 添加经纬网
                gl = ax.gridlines(draw_labels=True, xlocs=None, ylocs=None)
                gl.top_labels = False
                gl.right_labels = False
                gl.xformatter = LONGITUDE_FORMATTER
                gl.yformatter = LATITUDE_FORMATTER
                
                # 设置标题（包含时间信息）
                if params.title:
                    # 尝试从文件名中提取时间信息
                    time_match = re.search(r'(\d{6})', os.path.basename(nc_file))
                    if time_match:
                        time_str = time_match.group(1)
                        year = time_str[:4]
                        month = time_str[4:6]
                        title_with_time = f"{params.title} - {year}年{month}月"
                    else:
                        title_with_time = f"{params.title} - 第{i+1}帧"
                    ax.set_title(title_with_time, fontsize=14)
                
                # 保存当前帧
                frame_path = os.path.join(temp_dir, f"frame_{i:03d}.png")
                plt.savefig(frame_path, bbox_inches='tight', dpi=params.dpi)
                frame_paths.append(frame_path)
                
                # 清理当前图形
                plt.close(fig)
            
            # 生成GIF
            print("正在生成GIF动画...")
            images = []
            for frame_path in frame_paths:
                img = Image.open(frame_path)
                images.append(img)
            
            # 处理输出文件名
            if params.output_filename is None:
                output_filename = f"hydrology_gif_{uuid.uuid4().hex[:8]}.gif"
            else:
                output_filename = params.output_filename
                if not output_filename.endswith('.gif'):
                    output_filename += '.gif'
            
            output_path = os.path.join(OUTPUT_DIR, output_filename)
            
            # 确保输出目录存在
            Path(output_path).parent.mkdir(parents=True, exist_ok=True)
            
            # 保存GIF
            if images:
                images[0].save(
                    output_path,
                    save_all=True,
                    append_images=images[1:],
                    duration=int(params.gif_duration * 1000),  # 转换为毫秒
                    loop=params.gif_loop,
                    optimize=True
                )
            
            print(f"GIF生成完成: {output_path}")
            
            # 记录成功返回数据
            result = {
                "status": "success",
                "output_path": os.path.abspath(output_path),
                "relative_path": output_path,
                "metadata": {
                    "gif_file_pattern": params.gif_file_pattern,
                    "variable": params.variable,
                    "level": params.level,
                    "frame_count": len(nc_files),
                    "files_used": [os.path.basename(f) for f in nc_files],
                    "extent": [float(lon.min()), float(lon.max()), float(lat.min()), float(lat.max())],
                    "size_inches": params.figsize,
                    "dpi": params.dpi,
                    "title": params.title,
                    "duration": params.gif_duration,
                    "loop": params.gif_loop,
                    "value_range": [float(vmin), float(vmax)],
                    "levels": levels.tolist() if params.gif_integer_levels else None,
                    "integer_levels": params.gif_integer_levels,
                    "north_arrow": params.add_north_arrow,
                    "scale_bar": params.add_scale_bar,
                    "scale_bar_length": params.scale_bar_length if params.add_scale_bar else None,
                    "basemap": "TianDiTu"
                }
            }
            
            return result
            
        finally:
            # 清理临时文件
            import shutil
            try:
                shutil.rmtree(temp_dir)
            except:
                pass
            plt.close('all')
    
    except Exception as e:
        # 错误处理时确保所有资源被正确清理
        try:
            plt.close('all')
            # 清理临时文件
            if 'temp_dir' in locals():
                import shutil
                shutil.rmtree(temp_dir)
        except:
            pass
        
        return {
            "status": "error",
            "message": str(e),
            "output_path": None
        }


def add_custom_scalebar(ax, length_km, location=(0.08, 0.97), linewidth=1, text_offset=0.01):
    """添加自定义比例尺"""
    x0, x1, y0, y1 = ax.get_extent(ccrs.PlateCarree())
    lon_start = x0 + (x1 - x0) * location[0]
    lat_start = y0 + (y1 - y0) * location[1]
    deg_per_km = 1.0 / (111.32 * np.cos(np.radians(lat_start)))
    length_deg = length_km * deg_per_km
    lon_end = lon_start + length_deg
    
    ax.plot([lon_start, lon_end], [lat_start, lat_start],
            color='black', linewidth=linewidth, transform=ccrs.PlateCarree())
    
    hook_size = (y1 - y0) * 0.005
    ax.plot([lon_start, lon_start], [lat_start - hook_size, lat_start + hook_size],
            color='black', linewidth=linewidth, transform=ccrs.PlateCarree())
    ax.plot([lon_end, lon_end], [lat_start - hook_size, lat_start + hook_size],
            color='black', linewidth=linewidth, transform=ccrs.PlateCarree())
    
    ax.text((lon_start + lon_end) / 2, lat_start + text_offset,
            f'{length_km}km', ha='center', va='bottom',
            transform=ccrs.PlateCarree(), fontsize=7)


def add_fancy_north_arrow(ax, location=(0.03, 0.1), size=0.08, fontsize=14):
    """添加指北针"""
    x, y = location
    x0, y0 = x, y - size / 2
    
    left_arrow = mpatches.Polygon(
        [[x0, y0],
         [x0 - size / 6, y0 - size / 2],
         [x0, y0 - size / 3]],
        closed=True,
        transform=ax.transAxes,
        color='black',
        zorder=5
    )
    
    right_arrow = mpatches.Polygon(
        [[x0, y0],
         [x0 + size / 6, y0 - size / 2],
         [x0, y0 - size / 3]],
        closed=True,
        transform=ax.transAxes,
        facecolor='white',
        edgecolor='black',
        linewidth=1,
        zorder=5
    )
    
    ax.add_patch(left_arrow)
    ax.add_patch(right_arrow)
    
    ax.text(x, y + size * 0.1, 'N',
            transform=ax.transAxes,
            ha='center', va='center',
            fontsize=fontsize,
            color='black',
            zorder=6)


# 便捷接口函数
def plot_hydrology_map(
    nc_filename: str,
    variable: str,
    level: int = 0,
    uv_nc_filename: Optional[str] = None,
    u_var: Optional[str] = None,
    v_var: Optional[str] = None,
    output_filename: Optional[str] = None,
    figsize: tuple = (12, 10),
    dpi: int = 300,
    title: Optional[str] = None,
    add_north_arrow: bool = True,
    add_scale_bar: bool = True,
    scale_bar_length: float = 200,
    skip_arrows: int = 1,
    vmin: Optional[float] = None,
    vmax: Optional[float] = None,
    num_levels: int = 20,
    integer_levels: bool = True,
    colorbar_extend: str = 'neither',
    create_gif: bool = False,
    gif_file_pattern: Optional[str] = None,
    gif_duration: float = 0.8,
    gif_loop: int = 0,
    gif_vmin: Optional[float] = None,
    gif_vmax: Optional[float] = None,
    gif_levels: Optional[int] = 20,
    gif_integer_levels: bool = True
) -> Dict[str, Any]:
    """
    绘制水文地图的便捷接口函数
    
    Args:
        nc_filename: NC文件名（在data文件夹中）
        variable: 要绘制的变量名
        level: 数据层级（默认0）
        uv_nc_filename: 流速数据NC文件名（可选）
        u_var: u分量变量名（可选）
        v_var: v分量变量名（可选）
        output_filename: 输出图片文件名（可选）
        figsize: 图像尺寸
        dpi: 图像分辨率
        title: 地图标题
        add_north_arrow: 是否添加指北针
        add_scale_bar: 是否添加比例尺
        scale_bar_length: 比例尺长度（km）
        skip_arrows: 流速箭头绘制间隔
        create_gif: 是否生成GIF动画
        gif_file_pattern: GIF文件匹配模式
        gif_duration: GIF每帧持续时间（秒）
        gif_loop: GIF循环次数
        gif_vmin: GIF图例最小值
        gif_vmax: GIF图例最大值
        gif_levels: GIF等值线级数
        gif_integer_levels: 是否使用整数等值线级别
        
    Returns:
        包含状态和输出路径的字典
    """
    params = PlottingParameters(
        nc_filename=nc_filename,
        variable=variable,
        level=level,
        uv_nc_filename=uv_nc_filename,
        u_var=u_var,
        v_var=v_var,
        output_filename=output_filename,
        figsize=figsize,
        dpi=dpi,
        title=title,
        add_north_arrow=add_north_arrow,
        add_scale_bar=add_scale_bar,
        scale_bar_length=scale_bar_length,
        skip_arrows=skip_arrows,
        vmin=vmin,
        vmax=vmax,
        num_levels=num_levels,
        integer_levels=integer_levels,
        colorbar_extend=colorbar_extend,
        create_gif=create_gif,
        gif_file_pattern=gif_file_pattern,
        gif_duration=gif_duration,
        gif_loop=gif_loop,
        gif_vmin=gif_vmin,
        gif_vmax=gif_vmax,
        gif_levels=gif_levels,
        gif_integer_levels=gif_integer_levels
    )
    
    return create_hydrology_map(params)


if __name__ == "__main__":
    # 示例使用1：生成单张图片
    print("示例1：生成单张温度分布图")
    result = plot_hydrology_map(
        nc_filename="chinasea_202212_temp.nc",
        variable="temp",
        title="中国海域温度分布图",
        output_filename="temperature_map.png"
    )
    
    print(f"状态: {result['status']}")
    if result['status'] == 'success':
        print(f"图片路径: {result['output_path']}")
        print(f"相对路径: {result['relative_path']}")
    else:
        print(f"错误信息: {result['message']}")
    
    print("\n" + "="*50 + "\n")
    
    # 示例使用2：生成GIF动画
    print("示例2：生成温度变化GIF动画")
    gif_result = plot_hydrology_map(
        nc_filename="chinasea_202212_temp.nc",  # 这个参数在GIF模式下会被忽略
        variable="temp",
        title="中国海域温度变化",
        output_filename="temperature_animation.gif",
        create_gif=True,
        gif_file_pattern="chinasea_*_temp.nc",  # 匹配所有月份的温度文件
        gif_duration=1.0,  # 每帧1秒
        gif_loop=0,  # 无限循环
        gif_vmin=10,  # 固定图例最小值
        gif_vmax=30,  # 固定图例最大值
        gif_levels=21,  # 21个级别会产生20个整数区间
        gif_integer_levels=True,  # 使用整数级别
        colorbar_extend='neither' # 确保GIF图例也没有箭头
    )
    
    print(f"GIF状态: {gif_result['status']}")
    if gif_result['status'] == 'success':
        print(f"GIF路径: {gif_result['output_path']}")
        print(f"相对路径: {gif_result['relative_path']}")
        print(f"帧数: {gif_result['metadata']['frame_count']}")
        print(f"使用的文件: {gif_result['metadata']['files_used']}")
    else:
        print(f"错误信息: {gif_result['message']}")   